<template>
  <el-button :icon="Plus" plain type="primary" @click="addMenuBtn"
    >新增菜单</el-button
  >

  <el-table
    :data="menuList"
    row-key="id"
    :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
    style="width: 100%; margin-top: 30px"
    :header-cell-style="{
      background: '#f8f8f9',
      height: '60px',
      color: '#000000',
    }"
  >
    <el-table-column prop="menuName" label="菜单名称" width="160" />
    <el-table-column prop="menuIcon" label="图标" width="120" />
    <el-table-column prop="menuPath" label="组件路径" width="600" />
    <el-table-column prop="createdAt" label="创建时间" width="300" />
    <el-table-column prop="operate" label="操作">
      <template #default="scope">
        <el-button
          type="primary"
          size="small"
          @click="openUpdateMenuBtn(scope.row)"
          >编辑</el-button
        >

        <el-popconfirm
          title="你确定要删除吗?"
          @confirm="deleteMenuBtn(scope.row)"
        >
          <template #reference>
            <el-button type="danger" size="small">删除</el-button>
          </template>
        </el-popconfirm>
      </template>
    </el-table-column>
  </el-table>

  <el-dialog v-model="dialogFormVisible" title="设置菜单" width="700">
    <el-form :model="form" :rules="rules" ref="ruleForm">
      <el-form-item label="上级菜单" :label-width="formLabelWidth">
        <el-tree-select
          v-model="parentName"
          :data="labelInitList"
          check-strictly
          :render-after-expand="false"
          @current-change="(data) => changeMenu(data)"
        />
      </el-form-item>
      <el-form-item
        label="菜单名称"
        :label-width="formLabelWidth"
        prop="menuName"
      >
        <el-input v-model="form.menuName" autocomplete="off" />
      </el-form-item>

      <el-form-item
        label="菜单路由"
        :label-width="formLabelWidth"
        prop="menuPath"
      >
        <el-input v-model="form.menuPath" autocomplete="off" />
      </el-form-item>

      <el-form-item
        label="菜单路由名称"
        :label-width="formLabelWidth"
        prop="menuRouterName"
      >
        <el-input v-model="form.menuRouterName" autocomplete="off" />
      </el-form-item>

      <el-form-item
        label="菜单组件"
        :label-width="formLabelWidth"
        prop="menuComponent"
      >
        <el-input v-model="form.menuComponent" autocomplete="off" />
      </el-form-item>

      <el-form-item
        label="菜单图标"
        :label-width="formLabelWidth"
        prop="menuIcon"
      >
        <el-input v-model="form.menuIcon" autocomplete="off" />
      </el-form-item>

      <el-form-item label="菜单类型" :label-width="formLabelWidth">
        <el-radio-group v-model="form.menuType">
          <el-radio value="1" size="large">目录</el-radio>
          <el-radio value="2" size="large">菜单</el-radio>
        </el-radio-group>
      </el-form-item>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取消</el-button>
        <el-button
          type="primary"
          v-if="isChange"
          @click="submitForm('ruleForm', 'update')"
          >修改</el-button
        >
        <el-button
          type="primary"
          v-else
          @click="submitForm('ruleForm', 'create')"
          >添加</el-button
        >
      </div>
    </template>
  </el-dialog>
</template>

<script setup>
import { ref, computed, onMounted, watch, nextTick } from "vue";
import { Plus } from "@element-plus/icons-vue";
import { useMenuStore } from "@/stores/model/menu";
import { ElMessage } from "element-plus";

const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
const menuStore = useMenuStore();
const menuList = ref([]);

onMounted(async () => {
  const res = await menuStore.getMenuList();
  if (res) {
    menuList.value = menuStore.menuList;
  }
});

const parentName = ref("");
const isChange = ref(false);

const form = ref({
  menuType: "1",
  menuParentId: 0,
  menuRouterName: "",
  menuName: "",
  menuIcon: "",
  menuPath: "",
  menuComponent: "",
});

const rules = computed(() => ({
  menuName: [
    {
      required: true,
      message: "请输入菜单名称",
      trigger: "blur",
    },
  ],
  menuPath: [
    {
      required: true,
      message:
        "菜单路由不能为空，目录必须以/开头，根目录下的菜单也需以/开头，其他菜单不能以/开头",
      trigger: "blur",
      validator: (rule, value, callback) => {
        if (!value?.trim()) return callback(new Error(rule.message));

        const isDirectory = form.value.menuType === "1";
        const startsWithSlash = value.startsWith("/");
        const isRootMenu = form.value.menuParentId === 0;

        // 目录必须 / 开头
        if (isDirectory && !startsWithSlash) {
          return callback(new Error("目录路由必须以/开头"));
        }

        // 菜单类型需要特殊处理
        if (!isDirectory) {
          // 根目录下的菜单要求 / 开头
          if (isRootMenu && !startsWithSlash) {
            return callback(new Error("根目录下的菜单路由必须以/开头"));
          }
          // 非根目录的菜单禁止 / 开头
          if (!isRootMenu && startsWithSlash) {
            return callback(new Error("非根目录的菜单路由不能以/开头"));
          }
        }

        callback();
      },
    },
  ],
  menuRouterName: [
    {
      required: true,
      message: "请输入菜单路由名称，用于vueRouter的name属性",
      trigger: "blur",
    },
  ],
  menuComponent: [
    {
      required: form.value.menuType === "2",
      message: "菜单组件必须填写",
      trigger: "blur",
    },
  ],
}));

const _dfs = (data) => {
  if (!data || !data.length) return [];
  return data.map((item) => {
    const children = _dfs(item.children);
    return {
      value: item.id,
      label: item.menuName,
      menuPath: item.menuPath,
      children: children.length > 0 ? children : [],
    };
  });
};

const data = computed(() => {
  return _dfs(menuList.value);
});

const labelInitList = computed(() => {
  const res = [];
  res.push({ value: -1, label: "根目录", children: [] });
  res.push(...data.value);
  return res;
});

const changeMenu = (data) => {
  console.log(data);
  if (data.value == -1) {
    form.value.menuParentId = 0;
    form.value.menuType = "1";
  } else {
    form.value.menuParentId = data.value;
  }

  nextTick(() => {
    ruleForm.value.validateField("menuPath", () => {});
  });
};

const addMenuBtn = () => {
  isChange.value = false;
  dialogFormVisible.value = true;
  parentName.value = "根目录";
  form.value = {
    menuType: "1",
    menuParentId: 0,
    menuRouterName: "",
    menuName: "",
    menuIcon: "",
    menuPath: "",
    menuComponent: "",
  };
};

const _selectParentName = (menuList, id) => {
  let flag = false;
  menuList.forEach((item) => {
    if (flag) return;
    if (item.id == id) {
      parentName.value = item.menuName;
      flag = true;
      return;
    }
    if (item.children && item.children.length > 0) {
      _selectParentName(item.children, id);
    }
  });
};

const openUpdateMenuBtn = (data) => {
  isChange.value = true;
  if (data.menuParentId == 0) {
    parentName.value = "根目录";
  } else {
    _selectParentName(menuList.value, data.menuParentId);
  }
  form.value = data;
  dialogFormVisible.value = true;
};

const updateMenu = async () => {
  console.log(form.value);
  const res = await menuStore.updateMenu(form.value);
  if (res) {
    ElMessage.success("修改成功");
    menuList.value = menuStore.menuList;
    dialogFormVisible.value = false;
  } else {
    ElMessage.error("修改失败");
  }
};

const createMenuBtn = async () => {
  const res = await menuStore.createMenu(form.value);
  if (res) {
    ElMessage.success("添加成功");
    menuList.value = menuStore.menuList;
    dialogFormVisible.value = false;
  } else {
    ElMessage.error("添加失败");
  }
};

const deleteMenuBtn = async (data) => {
  const res = await menuStore.deleteMenu(data.id);
  if (res) {
    ElMessage.success("删除成功");
    menuList.value = menuStore.menuList;
  } else {
    ElMessage.error("删除失败");
  }
};

const submitForm = (formName, action) => {
  ruleForm.value.validate((valid) => {
    if (valid) {
      if (action === "create") {
        createMenuBtn();
      } else if (action === "update") {
        updateMenu();
      }
    } else {
      console.log("验证失败!");
      return false;
    }
  });
};

const ruleForm = ref(null);
</script>

<style scoped></style>
